// Oh boy, why am I about to do this....
#ifndef NETWORK_H
#define NETWORK_H

#include "yolodef.h"

#ifdef __cplusplus
extern "C" {
#endif

#ifdef GPU
float train_networks(network* nets, int n, data d, int interval);
void sync_nets(network* nets, int n, int interval);
float train_network_datum_gpu(network net, float* x, float* y);
float* network_predict_gpu(network net, float* input);
float* get_network_output_gpu_layer(network net, int i);
float* get_network_delta_gpu_layer(network net, int i);
float* get_network_output_gpu(network net);
void forward_network_gpu(network net, network_state state);
void backward_network_gpu(network net, network_state state);
void update_network_gpu(network net);
#endif

float get_current_seq_subdivisions(network net);
int get_sequence_value(network net);
float get_current_rate(network net);
int get_current_batch(network net);
void free_network(network net);
void compare_networks(network n1, network n2, data d);
char* get_layer_string(LAYER_TYPE a);

network make_network(int n);
void forward_network(network net, network_state state);
void backward_network(network net, network_state state);
void update_network(network net);

float train_network(network net, data d);
float train_network_waitkey(network net, data d, int wait_key);
float train_network_batch(network net, data d, int n);
float train_network_sgd(network net, data d, int n);
float train_network_datum(network net, float* x, float* y);

matrix network_predict_data(network net, data test);
//LIB_API float *network_predict(network net, float *input);
//LIB_API float *network_predict_ptr(network *net, float *input);
float network_accuracy(network net, data d);
float* network_accuracies(network net, data d, int n);
float network_accuracy_multi(network net, data d, int n);
void top_predictions(network net, int n, int* index);
float* get_network_output(network net);
float* get_network_output_layer(network net, int i);
float* get_network_delta_layer(network net, int i);
float* get_network_delta(network net);
int get_network_output_size_layer(network net, int i);
int get_network_output_size(network net);
image get_network_image(network net);
image get_network_image_layer(network net, int i);
int get_predicted_class_network(network net);
void print_network(network net);
void visualize_network(network net);
int resize_network(network* net, int w, int h);
void set_batch_network(network* net, int b);
int get_network_input_size(network net);
float get_network_cost(network net);
//LIB_API network *load_network_custom(char *cfg, char *weights, int clear, int batch);
//LIB_API network *load_network(char *cfg, char *weights, int clear);

// network.c
LIB_API load_args get_base_args(network* net);
LIB_API float* network_predict(network net, float* input);
LIB_API float* network_predict_ptr(network* net, float* input);
LIB_API detection* get_network_boxes(network* net, int w, int h, float thresh, float hier, int* map, int relative, int* num, int letter);
LIB_API void free_detections(detection* dets, int n);
LIB_API void fuse_conv_batchnorm(network net);
LIB_API void calculate_binary_weights(network net);
LIB_API char* detection_to_json(detection* dets, int nboxes, int classes, char** names, long long int frame_id, char* filename);
LIB_API layer* get_network_layer(network* net, int i);
//LIB_API detection *get_network_boxes(network *net, int w, int h, float thresh, float hier, int *map, int relative, int *num, int letter);
LIB_API detection* make_network_boxes(network* net, float thresh, int* num);
LIB_API void reset_rnn(network* net);
LIB_API float* network_predict_image(network* net, image im);
LIB_API float validate_detector_map(char* datacfg, char* cfgfile, char* weightfile, float thresh_calc_avg_iou, const float iou_thresh, const int map_points, network* existing_net);
LIB_API void train_detector(char* datacfg, char* cfgfile, char* weightfile, int* gpus, int ngpus, int clear, int dont_show, int calc_map, int mjpeg_port, int show_imgs);
LIB_API void test_detector(char* datacfg, char* cfgfile, char* weightfile, char* filename, float thresh,
    float hier_thresh, int dont_show, int ext_output, int save_labels, char* outfile, int letter_box);
LIB_API int network_width(network* net);
LIB_API int network_height(network* net);
LIB_API void optimize_picture(network* net, image orig, int max_layer, float scale, float rate, float thresh, int norm);


int get_network_nuisance(network net);
int get_network_background(network net);
//LIB_API void fuse_conv_batchnorm(network net);
//LIB_API void calculate_binary_weights(network net);
network combine_train_valid_networks(network net_train, network net_map);
void copy_weights_net(network net_train, network* net_map);
void free_network_recurrent_state(network net);
void randomize_network_recurrent_state(network net);
void remember_network_recurrent_state(network net);
void restore_network_recurrent_state(network net);

#ifdef __cplusplus
}
#endif

#endif
